﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
using log4net;
using RollBack.src.ui;
using RollBackLib.src.utils;
using System.Net.Sockets;
using RollBack.src;
using System.Threading;
using System.Configuration;
using Microsoft.Win32;
using System.IO;
using RollBackLib.src.core;
using RollBackLib.src.ui.Dialogs.Preferences;
using RollBackUI;
using RollBackUI.src.ui.Dialogs.Preferences;

namespace RollBack
{
    /// <summary>
    /// The main form application
    /// </summary>
    public partial class BackupAppForm : Form
    {
        private static readonly ILog log = LogManager.GetLogger(typeof(BackupAppForm));
        private AboutBox m_aboutBox = new AboutBox();
        private System.Windows.Forms.NotifyIcon m_systemTrayNotifyIcon;
        private System.Windows.Forms.ContextMenu m_trayIconContextMenu;
        private volatile bool m_exitApplication = false;

        public BackupAppForm()
        {
            AppUI.relocateAppFiles();
            InitializeComponent();
            this.Shown += new EventHandler(BackupAppForm_Shown);
            setStartupProperties();
        }

        void BackupAppForm_Shown(object sender, EventArgs e)
        {
            this.SuspendLayout();
            loadLastProject();
            m_driveAndBackupsetPanel.afterShown();
            setSavedApplicationSize();
            this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            this.SetStyle(ControlStyles.DoubleBuffer, false);
            this.ResumeLayout(false);
        }


        /// <summary>
        /// Change some properties of the application like
        ///  - App size
        ///  - Title.
        /// </summary>
        private void setStartupProperties()
        {
            string startMinimized = "/Minimized";
            bool startMini = false;
            foreach (string str in Environment.GetCommandLineArgs())
            {
                if (str.Equals(startMinimized, StringComparison.CurrentCultureIgnoreCase))
                {
                    startMini = true;
                }
            }
            if (startMini)
            {
                hideApplication();
            }
            // set the "Settings -> Start when windows starts" menu item
            string filePath = getStartupFileShortcut();
            startWhenWindowsStartsToolStripMenuItem.Checked = false;
            if (File.Exists(filePath))
            {
                startWhenWindowsStartsToolStripMenuItem.Checked = true;
            }

            System.Drawing.Size sz = RollbackUI.Default.ApplicationSize;
            log.Debug("Got application size as " + sz.ToString());
            this.m_driveAndBackupsetPanel.Dock = DockStyle.Fill;
            this.Dock = DockStyle.Fill;

            if (sz.Width < 800)
            {
                sz.Width = 800;
            }
            if (sz.Height < 640)
            {
                sz.Height = 640;
            }
            log.Debug("Changing application size to " + sz.ToString());
            this.Size = sz;              
        }

        private void setSavedApplicationSize()
        {
            try
            {
                String betaStatus = "";
                // set the title of the application
                string version = "Version -  " + AppUI.AssemblyVersion + " Build " + SVNVersionInfo.Revision + betaStatus;
                this.Text = "Rollback - " + version;
                m_driveAndBackupsetPanel.restoreUISettings();
            }
            catch (Exception e)
            {
                log.Warn("Could not load startup configuration", e);
            }

        }

        private void saveExecutablePathAsShortcut(string fileName)
        {
            IWshRuntimeLibrary.WshShellClass WshShell = null;
            try
            {
                // Create a new instance of WshShellClass
                WshShell = new IWshRuntimeLibrary.WshShellClass();
                // Create the shortcut
                IWshRuntimeLibrary.IWshShortcut MyShortcut;
                // Choose the path for the shortcut
                MyShortcut = (IWshRuntimeLibrary.IWshShortcut)WshShell.CreateShortcut(fileName);
                // Where the shortcut should point to
                MyShortcut.TargetPath = Application.ExecutablePath;
                MyShortcut.Arguments = " /Minimized";
                // Description for the shortcut
                MyShortcut.Description = "Run Rollback";
                // Location for the shortcut's icon
                //MyShortcut.IconLocation = Application.StartupPath + @"\app.ico";
                // Create the shortcut at the given path
                MyShortcut.Save();
            }
            catch (Exception e)
            {
                log.Warn("Error creating shortcut",e);
                AppUI.ShowException("Error creating shortcut", e);
            }
        }

        /// <summary>
        /// Minimize and hide the application
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void BackupAppForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (!m_exitApplication)
            {
                e.Cancel = true;
                hideApplication();
            }
            else
            {
                if (!shutdownApplication())
                {
                    e.Cancel = true;
                }
            }
        }

        private bool shutdownApplication( )
        {
            bool canShutdown = true;
            if (BackupRestoreRunner.BackupRunning)
            {
                this.m_exitApplication = false;
                canShutdown = false;
                AppUI.ShowMessage("Cannot shutdown, a backup operation is in progress.");
            }
            else
            {
                bool success = this.m_driveAndBackupsetPanel.shutdownThreads();
                if (success)
                {
                    log.Info("Form is closing.");
                    try
                    {
                        m_driveAndBackupsetPanel.shutdown();
                    }
                    catch (Exception ex)
                    {
                        log.Warn("Caught an exception while shutting down", ex);
                        AppUI.ShowException(ex.Message, ex);
                    }

                    try
                    {
                        RollbackUI.Default.ApplicationSize = this.Size;
                        RollbackUI.Default.Save();
                    }
                    catch (Exception ex)
                    {
                        log.Warn("Could not save application configuration", ex);
                    }
                }
                else
                {
                    canShutdown = false;
                    log.Warn("Cannot shutdown, scheduler thread is still running ");
                }
            }
            return canShutdown;
        }

        internal void setStatusText(string s)
        {
            this.m_toolStripStatusLabel.Text = s;
        }

        /// <summary>
        /// Load the last saved Backup Project
        /// </summary>
        internal void loadLastProject()
        {
            string file = AppUI.getSettingsFile();
            loadProjectFile(file);
        }

        private void loadProjectFile(string file)
        {
            m_driveAndBackupsetPanel.LoadSavedBackupSets(file);
            this.m_openConfigFileMenuItem.ToolTipText = m_driveAndBackupsetPanel.getCurrentBackupProfile();
            this.openCurrentXMLConfigurationFileToolStripMenuItem.ToolTipText = m_driveAndBackupsetPanel.getCurrentBackupProfile();
        }

        private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            m_aboutBox.ShowDialog();
        }

        private void openToolStripMenuItem_Click(object sender, EventArgs e)
        {
            openAndLoadBackupXMLFile();
        }

        private void openAndLoadBackupXMLFile()
        {
            if (BackupRestoreRunner.BackupRunning)
            {
                AppUI.ShowMessage("Backups are currently running.\nClose all backup jobs before opening a new Backup set");
            }
            else
            {
                OpenFileDialog fd = new OpenFileDialog();
                fd.AutoUpgradeEnabled = true;
                fd.InitialDirectory = AppUI.getAppDataPath();
                fd.Filter = "BackupSet Files (*.xml)|";
                if (fd.ShowDialog() == DialogResult.OK && fd.FileName != null)
                {
                    loadProjectFile(fd.FileName);
                }
            }
        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if(BackupRestoreRunner.BackupRunning) 
            {
                AppUI.ShowMessage("Backups are currently running\r\nStop all backups before exiting.");
            } else {
                this.m_exitApplication = true;
                Application.Exit();
            }
        }

        internal string getStatusMessage()
        {
            return m_toolStripStatusLabel.Text;
        }

        private void toolStripMenuItem1_Click(object sender, EventArgs e)
        {
            openSettingsFile();
        }

        private static void openSettingsFile()
        {
            Process notepad = new Process();
            notepad.StartInfo.FileName = AppUI.getSettingsFile();
            notepad.Start();
        }

        /// <summary>
        /// Create a new backup job 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void newToolStripButton_Click(object sender, EventArgs e)
        {
            m_driveAndBackupsetPanel.createNewBackupJob();
        }

        /// <summary>
        /// open a new xml file containing a list of backup jobs.
        /// Close the current set.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void openToolStripButton_Click(object sender, EventArgs e)
        {
            openAndLoadBackupXMLFile();
        }

        /// <summary>
        /// Save all backup jobs
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void saveToolStripButton_Click(object sender, EventArgs e)
        {
            m_driveAndBackupsetPanel.m_backupSetComposite.updateAndSaveAllBackupJobs();
        }

        /// <summary>
        /// Delete the currently shown backup tab
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void cutToolStripButton_Click(object sender, EventArgs e)
        {
            m_driveAndBackupsetPanel.closeBackupJob();
        }

        private void m_clearMessagesToolbarButton_Click(object sender, EventArgs e)
        {
            this.m_driveAndBackupsetPanel.processClearButton();
        }

        private void openToolStripButton_ButtonClick(object sender, EventArgs e)
        {
            openAndLoadBackupXMLFile();
        }

        private void openBackupJobSetToolStripMenuItem_Click(object sender, EventArgs e)
        {
            openAndLoadBackupXMLFile();
        }

        private void openCurrentXMLConfigurationFileToolStripMenuItem_Click(object sender, EventArgs e)
        {
            openSettingsFile();
        }

        private void m_exitSysTrayMenuItem_Click(object sender, EventArgs e)
        {
            this.m_exitApplication = true;
            this.Close();
        }

        /// <summary>
        /// Add/Remove the program from the "Startup" folder.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void startWhenWindowsStartsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            /*
            string regKey = "ShastramRollback";
            RegistryKey rkey = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Run", true);
             */
            string fileName = getStartupFileShortcut();
            if (startWhenWindowsStartsToolStripMenuItem.Checked)
            {
                // remove from startup
                //rkey.DeleteValue(regKey, false);
                if (File.Exists(fileName))
                {
                    File.Delete(fileName);
                    log.Info("Removing program <" +fileName + "> from startup.");
                }
            }
            else
            {
                // add to startup
                //string path = "\"" + Application.ExecutablePath + "\"   " + "/Minimized" ;
                //rkey.SetValue(regKey, path);
                //rkey.Close();
                saveExecutablePathAsShortcut(fileName);
                log.Info("Adding program <" + fileName + "> to startup.");
            }
            startWhenWindowsStartsToolStripMenuItem.Checked = !startWhenWindowsStartsToolStripMenuItem.Checked;
        }

        /// <summary>
        /// Return the path to the shortcut in the users startup directory.
        /// </summary>
        /// <returns></returns>
        private string getStartupFileShortcut( ) 
        {
            string startupFolder = Environment.GetFolderPath(Environment.SpecialFolder.Startup);

            string fileName = @startupFolder + "\\Run Rollback.lnk";
            return fileName;
        }

        private void optionsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            m_preferencesDialog = new RollBackLib.src.ui.Dialogs.PreferencesDialog();
            // load the email and smtp details from the xml file.
            EmailAndSmtpTable emailDao = EmailAndSmtpTable.load();

            //EmailDetailsDialog emailDetailsDailog = new EmailDetailsDialog();
            //emailDetailsDailog.populateDialog(emailDao);
            StandardEmailDetail standardEmail = new StandardEmailDetail( );
            standardEmail.populateEmailDetails(emailDao);
            m_preferencesDialog.addPreference("Mail", null, standardEmail);
            DialogResult result = m_preferencesDialog.ShowDialog();
            if (result == DialogResult.OK)
            {
                EmailAndSmtpTable.save(standardEmail.getEmailAndSmtpData());
                //EmailAndSmtpTable.save(emailDetailsDailog.getEmailAndSmtpData());
            }
        }
    }
}
